package entities;

import java.io.Serializable;
import java.util.*;

/**
 *
 * @author Dragan Sahpaski
 */
public class ViewGraph implements Serializable{

    // This is the root view with the most detailed level of aggregation.
    private ViewGene root;
    // ViewGene domaing mappers for all views in all levels of aggregation
    private List<ViewGene> allViews;

    public ViewGraph(ViewGene root) {
        this.root = root;
    }

    public Table getRoot() {
        return root;
    }

    public List<ViewGene> getAllViews() {
        return allViews;
    }

    /*
     * Todo documentation
     */
    private List<Table> buildDimensionSubGraph(Table rootRelation) {
        List<Table> allChildren = new ArrayList<Table>();
        allChildren.addAll(rootRelation.getFKRelations());
        for (Table rel : rootRelation.getFKRelations()) {
            allChildren.addAll(buildDimensionSubGraph(rel));
        }
        rootRelation.setAllChildren(allChildren);
        // Remove duplicates
        LinkedHashSet<Relation> set = new LinkedHashSet(allChildren);
        allChildren.clear();
        allChildren.addAll(set);
        return allChildren;
    }

    private boolean isParentOf(Table parent, Table view) {
        if (parent.equals(view)) {
            return false;
        }
        // Foreach dimension of parent and view check if view.relation
        // is less detailed than parent.relation
        // and if they are in the same tree path to the root
        for (int k = 0; k < view.getFKRelations().size(); k++) {
            Table parentDimTable = parent.getFKRelations().get(k);
            Table viewDimTable = view.getFKRelations().get(k);
            if (parentDimTable != viewDimTable &&
                    !parentDimTable.getAllChildren().contains(viewDimTable)) {
                return false;
            }
        }
        return true;
    }

    /* Set the parents of all the views.
     * view1.isParentOf(view2) if view1 is more detailed from view2
     * in every dimension.
     */
    private void linkViewParents() {
        for (Table view : allViews) {
            for (Table potentialParent : allViews) {
                if (isParentOf(potentialParent, view)) {
                    view.getAllParents().add(potentialParent);
                }
            }
        }
    }

    /*
     * Todo documentation
     */
    public void buildViewGraph() {
        allViews = new ArrayList<ViewGene>();
        allViews.add(root);
        int dimensionIndex = 0;
        for (Table dimTable : root.getFKRelations()) {
            this.buildDimensionSubGraph(dimTable);
            List<Table> viewsUntillNow = new ArrayList<Table>();
            viewsUntillNow.addAll(allViews);
            for (Table table : dimTable.getAllChildren()) {
                for (Table v : viewsUntillNow) {
                    List<Table> fkRelations = new ArrayList<Table>();
                    fkRelations.addAll(v.getFKRelations());
                    fkRelations.set(dimensionIndex, table);
                    String viewName = "";
                    for (Table fk : fkRelations) {
                        viewName += fk.getName().substring(0, 1);
                    }
                    ViewGene view = new ViewGene(viewName, fkRelations);
                    allViews.add(view);
                }
            }
            dimensionIndex++;
        }
        linkViewParents();
    }

    @Override
    public String toString() {
        String str = "";
        int i = 0;
        for (Table v : allViews) {
            str += "\n" + i++ + ":" + v.toString();
        }
        return str;
    }
}
